#include "PPProcess.h"

#include <string.h>

PFProcess::PFProcess(void)
{
	iClassID = PPLC_CLASS_PROCESS + PPLC_CLASS_GENERIC;

	iStatus = STATUS_INIT;
}

int PFProcess::Create()
{
	iMemorySize = 0;
    iCycleCount = 0;

	pProcessMemoryWrite = 0;
	pProcessMemoryRead = 0;

	iStatus = STATUS_STOP;

#ifdef _DEBUG
		printf("PFProcess: Generic process with instance %08x created successfully.\n", iInstanceID);
#endif

	return PF_RESULT_SUCCESS;
}

int PFProcess::Run() 
{ 
	/* Always fail a run on a generic process. */
	return PF_ERROR_NOT_IMPLEMENTED;
}

int PFProcess::ReadMemory(unsigned int dwAddress, unsigned int iLength, void * pData)
{
    /**
     * Default memory read implmentation: Only employ parameter sanity check. 
     */
	if(pProcessMemoryRead == 0)
        /* Memory is not initialized, call Create() first. */
		return PF_ERROR_NOT_INITIALIZED + PF_RESULT_FAIL;

	if(dwAddress >= iMemorySize)
        /* Address requested is not within my memory space. */
		return PF_ERROR_ADDRESS_OUT_OF_RANGE + PF_RESULT_FAIL;

	if(dwAddress + iLength >= iMemorySize)
	    /* Amount of memory attempted to read is too big. */
		return PF_ERROR_INVALID_BLOCK_SIZE + PF_RESULT_FAIL;
	
	if(iStatus & STATUS_BUSY)
	    /* Process data is not valid. */
		return PF_ERROR_PERMISSION_DENIED + PF_RESULT_FAIL;
		
	if(pData == 0)
	    /* Pointer where the data needs to go is not valid. */
        return PF_ERROR_INVALID_PARAMETER + PF_RESULT_FAIL;
        
    memcpy(pData, pProcessDataRead, iLength);
    
    return PF_RESULT_SUCCESS;
}

int PFProcess::WriteMemory(unsigned int dwAddress, unsigned int iLength, void * pData)
{
    /**
     * Default memory write implmentation: Only employ parameter sanity check. 
     */
	if(pProcessMemoryWrite == 0)
		return PF_ERROR_NOT_INITIALIZED + PF_RESULT_FAIL;

	if(dwAddress >= iMemorySize)
		return PF_ERROR_ADDRESS_OUT_OF_RANGE + PF_RESULT_FAIL;

	if(dwAddress + iLength >= iMemorySize)
		return PF_ERROR_INVALID_BLOCK_SIZE + PF_RESULT_FAIL;
	
	if(iStatus & STATUS_BUSY)
		return PF_ERROR_PERMISSION_DENIED + PF_RESULT_FAIL;

	if(pData == 0)
	    /* Pointer where the data needs to come from is not valid. */
        return PF_ERROR_INVALID_PARAMETER + PF_RESULT_FAIL;
        		
    memcpy(pProcessDataWrite, pData, iLength);
    
    return PF_RESULT_SUCCESS;
}

int PFProcess::_executeCycle()
{
    if(iStatus == STATUS_INIT)
    {
        /* Internal memory is not valid yet. Terminate. */
        return PF_RESULT_FAILURE + PF_ERROR_NOT_INITIALIZED;
    }
    
    /* Only do something if the process is supposed to be running */
    if(iStatus == STATUS_READY)
    {
        /* Block memory access if the process is cycling */
        iStatus = STATUS_BUSY;
        
        pProcessData = pProcessDataRead;
              
        /* Take memory from input PD and prepare it for execution. */
        memcpy(pProcessDataRead, pProcessDataWrite, iMemorySize);

        int ret = Run();      
        
        if(ret != PF_RESULT_SUCCESS)
        {
              iStatus = STATUS_FAULT;
              
              pProcessData = 0;
              
              return ret;
        }
        
        pProcessData = 0;
        
        iCycleCount++;
        
        /* After this, pProcessDataRead contains data valid for this cycle. */
        iStatus = STATUS_READY;
        
        
        return PF_RESULT_SUCCESS;
    }
    
    if(status == STATUS_HALT || STATUS_STOP || STATUS_BUSY)
    {
        /* Process has been recursively called, paused or terminated gracefully, execute NOP. */
        return PF_RESULT_SUCCESS;
    }
}

PFProcess::~PFProcess(void)
{

}
